home *** CD-ROM | disk | FTP | other *** search
- /* Functions for drawing things using QuickDraw and for changing attributes
- of graf ports.
-
- Revision History:
-
- 94/01/02 aih
- - added function to set color hilite mode
-
- 93/12/02 aih
- - added functions for dragging rectangles and regions
-
- 93/11/17 aih
- - moved InvalXor from TextScrollLib.c
-
- 93/11/15 aih
- - added function to convert a region from global to local coordinates
-
- 92/03/20 AIH
- - Added function to draw a small icon
-
- 92/02/26 AIH
- - Removed patch to SetCursor since it didn't do much for efficiency
-
- 92/02/20 AIH
- - Added function to draw thick input focus border
-
- 91/05/15 AIH
- - Added patch to SetCursor to improve the efficiency of the cursor
- setting function
-
- 91/05/14 AIH
- - Improved efficiency of function for setting the cursor
-
- 91/04/05 AIH
- - Added function to convert a local region to a global region.
- This function doesn't start with the prefix 'Draw', but I decided
- that's ok since its relationship to the ToolBox routine LocalToGlobal
- is obvious, and therefore its relationship to QuickDraw should also
- obvious. Besides, I couldn't think of a better name.
-
- 91/03/25 AIH
- - Added function to determine if the cursor was changed
- - Added constant for the arrow cursor
-
- 91/03/17-18 AIH
- - Ifdef'd out unused functions
- - Added a few comments.
-
- 91/02/27 AIH
- - Added functions for creating a big port and for dragging a rectangle
-
- 91/02/26 AIH
- - Moved function for drawing an icon at a random position into this
- file from the blackout library
-
- 91/02/08 AIH
- - Removed some more functions that weren't really needed
-
- 91/01/21 AIH
- - Removed some functions I never use
-
- 91/01/05 Ari Halberstadt (AIH)
- - Inserted this standard header in all files */
-
- #include <limits.h>
- #include <stdlib.h>
- #include "DrawLib.h"
- #include "MemoryLib.h"
- #include "RectangleLib.h"
- #include "ScreenLib.h"
-
- /*----------------------------------------------------------------------*/
- /* hilite mode */
- /*----------------------------------------------------------------------*/
-
- /* set hilite mode for color hiliting (IM-V, p61) */
- void SetHiliteMode(void)
- {
- #define HiliteMode (*(char *) (0x938))
- BitClr(&HiliteMode, pHiliteBit);
- }
-
- /*----------------------------------------------------------------------*/
- /* setting the cursor */
- /*----------------------------------------------------------------------*/
-
- /* Set the cursor with the given resource ID. To set to the arrow
- cursor use the constant arrowCursor. */
- void DrawCursor(short id)
- {
- CursHandle crsr = NULL;
-
- if (id == arrowCursor)
- SetCursor(&arrow);
- else {
- crsr = GetCursor(id);
- if (crsr && *crsr)
- SetCursor(*crsr); /* won't move or purge memory */
- }
- }
-
- /*----------------------------------------------------------------------*/
- /* manipulating regions */
- /*----------------------------------------------------------------------*/
-
- /* convert region to global coordinates */
- void LocalToGlobalRgn(RgnHandle rgn)
- {
- Point origin = { 0, 0 };
-
- LocalToGlobal(&origin);
- OffsetRgn(rgn, origin.h, origin.v);
- }
-
- /* convert region to local coordinates */
- void GlobalToLocalRgn(RgnHandle rgn)
- {
- Point origin = { 0, 0 };
-
- LocalToGlobal(&origin);
- OffsetRgn(rgn, -origin.h, -origin.v);
- }
-
- /* convert region to global coordinates */
- void PortToGlobalRgn(RgnHandle rgn, GrafPtr port)
- {
- GrafPtr svport;
-
- GetPort(&svport);
- SetPort(port);
- LocalToGlobalRgn(rgn);
- SetPort(svport);
- }
-
- /* convert region to port coordinates */
- void GlobalToPortRgn(RgnHandle rgn, GrafPtr port)
- {
- GrafPtr svport;
-
- GetPort(&svport);
- SetPort(port);
- GlobalToLocalRgn(rgn);
- SetPort(svport);
- }
-
- /*----------------------------------------------------------------------*/
- /* manipulating points */
- /*----------------------------------------------------------------------*/
-
- /* convert a global coordinate to the port's coordinate */
- void GlobalToPort(Point *pt, GrafPtr port)
- {
- GrafPtr oldPort;
- GetPort(&oldPort);
- SetPort(port);
- GlobalToLocal(pt);
- SetPort(oldPort);
- }
-
- /* convert a port coordinate to the global coordinate */
- void PortToGlobal(Point *pt, GrafPtr port)
- {
- GrafPtr oldPort;
- GetPort(&oldPort);
- SetPort(port);
- LocalToGlobal(pt);
- SetPort(oldPort);
- }
-
- /*----------------------------------------------------------------------*/
- /* Functions for getting and setting text attributes of the current port.
- These are similar to the ToolBox procedures GetPenState, SetPenState,
- and PenNormal. */
- /*----------------------------------------------------------------------*/
-
- /* get the text attributes */
- void GetTextState(TextState *text)
- {
- GrafPtr port;
-
- GetPort(&port);
- text->font = port->txFont;
- text->face = port->txFace;
- text->mode = port->txMode;
- text->size = port->txSize;
- }
-
- /* set the text attributes */
- void SetTextState(const TextState *text)
- {
- TextFont(text->font);
- TextFace(text->face);
- TextMode(text->mode);
- TextSize(text->size);
- }
-
- /* set the text attributes to their defaults */
- void TextNormal(void)
- {
- TextFont(0);
- TextFace(0);
- TextSize(0);
- TextMode(srcOr);
- }
-
- /*----------------------------------------------------------------------*/
- /* drawing icons */
- /*----------------------------------------------------------------------*/
-
- /* Draw a SICN, a resource type which defines a 16 by 16 bit image,
- at the given location. SICN is specified by a resource ID number
- and a one-based index into the SICN list. The location specifies
- the top left corner of the SICN in the local coordinates of the
- current port. Adapted from the THINK Class Library utilities. */
- void DrawSICN(Handle sicn, Point pt, short index)
- {
- SignedByte state = 0;
- BitMap image;
- Rect bounds;
- GrafPtr port = NULL;
-
- require(index >= 1);
- require(HandleSize(sicn) >= 32 * (index - 1));
- state = HandleLock(sicn);
- GetPort(&port);
- image.baseAddr = *sicn + 32 * (index - 1);
- image.rowBytes = 2;
- SetRect(&bounds, pt.h, pt.v, pt.h + 16, pt.v + 16);
- image.bounds = bounds;
- CopyBits(&image, &port->portBits, &bounds, &bounds, srcCopy, NULL);
- HandleRestore(sicn, state);
- }
-
- /* DrawIcon is like PlotIcon except that it operates on an 'ICN#'
- resource instead of an 'ICON' resource. Also, before the icon
- is drawn, a hole is punched using the icon's mask. DrawIcon should
- work on all versions of the Macintosh since it is used to draw an
- INIT's loaded/not loaded icon at the bottom of the screen. */
- void DrawIcon(Handle icon, Point pt)
- {
- SignedByte state = 0;
- BitMap srcBits;
- Rect srcRect;
- Rect dstRect;
- GrafPtr port = NULL;
-
- require(HandleSize(icon) >= 256);
- state = HandleLock(icon);
- SetRect(&dstRect, pt.h, pt.v, pt.h + 32, pt.v + 32);
- GetPort(&port);
- srcBits.baseAddr = *icon + 128;
- srcBits.rowBytes = 4;
- SetRect(&srcRect, 0, 0, 32, 32);
- srcBits.bounds = srcRect;
- CopyBits(&srcBits, &port->portBits, &srcRect, &dstRect, srcBic, 0);
- srcBits.baseAddr = *icon;
- CopyBits(&srcBits, &port->portBits, &srcRect, &dstRect, srcOr, 0);
- HandleRestore(icon, state);
- }
-
- /*----------------------------------------------------------------------*/
- /* invalidating regions and rectangles */
- /*----------------------------------------------------------------------*/
-
- /* Invalidate and erase the region which is not common to both regions.
- This is most useful when resizing an object or window, since
- it invalidates only the region that has changed. */
- void InvalXorRgn(RgnHandle rgn1, RgnHandle rgn2)
- {
- RgnHandle xor;
-
- xor = BeginRgn();
- XorRgn(rgn1, rgn2, xor);
- InvalRgn(xor);
- EraseRgn(xor);
- EndRgn(xor);
- }
-
- /* same as InvalXorRgn but operates on rectangles */
- void InvalXorRect(const Rect *r1, const Rect *r2)
- {
- RgnHandle rgn1, rgn2;
-
- require(RectValid(r1));
- require(RectValid(r2));
- rgn1 = BeginRgn();
- rgn2 = BeginRgn();
- RectRgn(rgn1, r1);
- RectRgn(rgn2, r2);
- InvalXorRgn(rgn1, rgn2);
- EndRgn(rgn1);
- EndRgn(rgn2);
- }
-
- /*----------------------------------------------------------------------*/
- /* drawing borders */
- /*----------------------------------------------------------------------*/
-
- void BorderRgn(const Rect *content, short width, short margin,
- Boolean visible, RgnHandle rgn)
- {
- RgnHandle inner, outer;
- Rect bounds;
-
- require(RectValid(content));
- require(ValidateRgn(rgn));
- require(width >= 0);
- require(margin >= 0);
- /* Return a region describing the frame rectangle (including the
- one border between it and the object it encloses). This is useful
- when you need to invalidate the border after an object has been
- moved or resized. */
- inner = BeginRgn();
- outer = BeginRgn();
- bounds = *content;
- if (visible)
- InsetRect(&bounds, width, width);
- RectRgn(outer, &bounds);
- if (! visible)
- InsetRect(&bounds, width, width);
- InsetRect(&bounds, margin, margin);
- RectRgn(inner, &bounds);
- DiffRgn(outer, inner, rgn);
- EndRgn(inner);
- EndRgn(outer);
- }
-
- void BorderDraw(const Rect *content, short width, short margin,
- Boolean visible)
- {
- RgnHandle rgn;
- PenState pen;
- Rect bounds;
-
- require(RectValid(content));
- require(width >= 0);
- require(margin >= 0);
- rgn = BeginRgn();
- GetPenState(&pen);
- PenNormal();
- bounds = *content;
- BorderRgn(&bounds, width, margin, visible, rgn);
- EraseRgn(rgn);
- if (visible) {
- check(width > 0);
- PenSize(width, width);
- FrameRect(&bounds);
- }
- EndRgn(rgn);
- SetPenState(&pen);
- }
-
- /*----------------------------------------------------------------------*/
- /* dragging regions and rectangles */
- /*----------------------------------------------------------------------*/
-
- /* Drag a gray outline of dragRgn. This function is used to drag
- windows and floating menus. The parameters are:
-
- dragRgn On entry, region to drag around, on exit moved to final
- position
-
- frameRgn When the mouse is released, if frameRgn doesn't intersect deskRgn
- then {0,0} is returned. FrameRgn maintains its position relative
- to dragRgn, so on exit it is also moved to its final position.
- FrameRgn is typically the drag region of a window.
-
- deskRgn Region enclosing desktop; typically the value of
- GetGrayRgn().
-
- limitRgn Region enclosed by desktop. If the mouse leaves limitRgn
- then the gray outline of dragRgn is hidden, though the mouse
- is still tracked. If the mouse is released outside of limitRgn,
- then {0,0} is returned.
-
- contRgn The region within which to continue dragging. If the mouse
- leaves contRgn the function immediately returns {0,0}.
-
- clipRgn The clip region of the port that dragging takes place in is
- set to clipRgn. The clip region is restored before the
- function returns.
-
- port The graf port to draw into, typically the window manager port.
-
- startPt The location of the mouse.
-
- It is very hard to explain this function without a diagram.
- This comment is accurate as of 93/12/03 */
- Point DragRgn(RgnHandle dragRgn, RgnHandle frameRgn,
- const RgnHandle deskRgn, const RgnHandle limitRgn,
- const RgnHandle contRgn, const RgnHandle clipRgn,
- GrafPtr port, Point startPt)
- {
- PenState pen; /* saved pen state */
- Point newPt, oldPt; /* current and previous mouse positions */
- Point offset = { 0, 0 }; /* result */
- Boolean visible = false; /* true if outline is visible */
- volatile RgnHandle svclipRgn = NULL; /* saved clip region */
- volatile GrafPtr savePort = NULL; /* saved port */
-
- require(ValidateRgn(dragRgn));
- require(ValidateRgn(frameRgn));
- require(ValidateRgn(deskRgn));
- require(ValidateRgn(limitRgn));
- require(ValidateRgn(contRgn));
- require(ValidateRgn(clipRgn));
- require(MemValid(port));
- if (! StillDown())
- return(offset); /* quick out */
- TRY {
-
- /* setup port */
- GetPort(&savePort);
- SetPort(port);
-
- /* setup pen */
- GetPenState(&pen);
- PenNormal();
- PenPat(gray);
- PenMode(patXor);
-
- /* set clip region */
- svclipRgn = BeginRgn();
- GetClip(svclipRgn);
- SetClip(clipRgn);
-
- /* draw outline */
- if (PtInRgn(startPt, limitRgn) && PtInRgn(startPt, contRgn)) {
- FrameRgn(dragRgn);
- visible = true;
- }
-
- /* drag outline */
- newPt = oldPt = startPt;
- while (StillDown() && PtInRgn(newPt, contRgn)) {
-
- /* get new mouse position */
- GetMouse(&newPt);
- LocalToGlobal(&newPt);
- if (newPt.h != oldPt.h || newPt.v != oldPt.v) {
-
- /* erase old outline and draw new outline */
- if (visible)
- FrameRgn(dragRgn);
- visible = false;
- OffsetRgn(dragRgn, newPt.h - oldPt.h, newPt.v - oldPt.v);
- OffsetRgn(frameRgn, newPt.h - oldPt.h, newPt.v - oldPt.v);
- if (PtInRgn(newPt, limitRgn)) {
- FrameRgn(dragRgn);
- visible = true;
- }
- oldPt = newPt;
- }
- }
-
- /* erase outline */
- if (visible)
- FrameRgn(dragRgn);
- visible = false;
-
- /* calculate offset if mouse was released in a valid destination region */
- if (PtInRgn(newPt, contRgn) && PtInRgn(newPt, limitRgn)) {
- SectRgn(frameRgn, deskRgn, frameRgn);
- if (! EmptyRgn(frameRgn)) {
- offset.h = newPt.h - startPt.h;
- offset.v = newPt.v - startPt.v;
- }
- }
- } CLEANUP {
- SetPenState(&pen);
- if (svclipRgn) {
- SetClip(svclipRgn);
- EndRgn(svclipRgn);
- }
- if (savePort)
- SetPort(savePort);
- } ENDTRY;
- return(offset);
- }
-
- /* drag a rectangle around; see DragRgn for more details */
- Point DragRect(const Rect *dragRect, const Rect *frameRect,
- const RgnHandle contRgn, const RgnHandle clipRgn, Point startPt)
- {
- Point offset = { 0, 0 }; /* change in position */
- GrafPtr wmgrPort = NULL; /* window manager's port */
- RgnHandle dragRgn = NULL; /* outline of region to drag */
- RgnHandle frameRgn = NULL; /* frame around region to drag */
- RgnHandle limitRgn = NULL; /* region within which to drag */
-
- require(RectValid(dragRect));
- require(RectValid(frameRect));
- require(ValidateRgn(contRgn));
- require(ValidateRgn(clipRgn));
- if (! StillDown())
- return(offset); /* quick out */
- dragRgn = BeginRgn(); RectRgn(dragRgn, dragRect);
- frameRgn = BeginRgn(); RectRgn(frameRgn, frameRect);
- limitRgn = BeginRgn(); CopyRgn(GetGrayRgn(), limitRgn);
- InsetRgn(limitRgn, SCREEN_MARGIN, SCREEN_MARGIN);
- GetWMgrPort(&wmgrPort);
- offset = DragRgn(dragRgn, frameRgn, GetGrayRgn(), limitRgn,
- contRgn, clipRgn, wmgrPort, startPt);
- EndRgn(dragRgn);
- EndRgn(frameRgn);
- EndRgn(limitRgn);
- return(offset);
- }
-